package log

import (
	"encoding/json"
	"fmt"
	"github.com/spf13/viper"
	"go.uber.org/zap"
)

var (
	Logger *zap.Logger
)

// InitLog 日志组件初始化函数
func InitLog() error {
	return logLoad()
}

type JsonConfig struct {
	Level            string        ` json:"level,omitempty" mapstructure:"level"`
	Encoding         string        `json:"encoding,omitempty" mapstructure:"encoding"`
	OutputPaths      []string      `json:"outputPaths,omitempty" mapstructure:"outputPaths"`
	ErrorOutputPaths []string      `json:"errorOutputPaths,omitempty" mapstructure:"errorOutputPaths"`
	InitialFields    InitialFields `json:"initialFields" mapstructure:"initialFields"`
	EncoderConfig    EncoderConfig `json:"encoderConfig" mapstructure:"encoderConfig"`
}
type InitialFields struct {
	Foo string `json:"foo,omitempty" mapstructure:"foo"`
}
type EncoderConfig struct {
	MessageKey   string `json:"messageKey,omitempty" mapstructure:"messageKey"`
	LevelKey     string `json:"levelKey,omitempty" mapstructure:"levelKey"`
	LevelEncoder string `json:"levelEncoder,omitempty" mapstructure:"levelEncoder"`
}

// 日志加载逻辑
func logLoad() error {
	// zap组件的日志配置对象
	var cfg zap.Config
	// 自定义的日志配置对象
	var jsonConfig JsonConfig
	// 注意这里反序列化时使用的是指针，另外结构体中属性需要大写（公开）
	// 将读取出来的日志配置反序列到对象中，用于后续的日志初始化使用
	if err := viper.UnmarshalKey("log", &jsonConfig); err != nil {
		return err
	}
	// 将自定义的日志对象初始化为[]byte
	cf, err := json.Marshal(jsonConfig)
	if err != nil {
		return err
	}
	fmt.Printf("%s\n", string(cf))
	// 将[]byte后的日志配置反序列为zap组件的日志对象，注意这里是因为viper的反序列化时对象类型不匹配导致问题，因此才增加了这一步
	//TODO 后续对其进行优化，直接使用viper组件反序列化为zap组件的配置对象。
	if err = json.Unmarshal(cf, &cfg); err != nil {
		return err
	}
	// 日志对象建立，整个框架里面均使用该Logger对象作为统一日志输出对象
	Logger, err = cfg.Build()
	if err != nil {
		return err
	}
	defer Logger.Sync()

	Logger.Info("logger construction succeeded")

	// 打开协程观察配置文件变更
	/*go func() {
		for {
			time.Sleep(time.Second * 5) // 每次请求后延迟

			// 刷新配置
			err := viper.WatchRemoteConfig()
			if err != nil {
				Logger.Error("unable to read remote config: %v", zap.Error(err))
				continue
			}

			// 将配置重新反序列化到对象中
			viper.Unmarshal(&jsonConfig)
		}
	}()*/
	return nil
}
